<?php


namespace App\Services;


use App\Models\Task;
use App\Models\TaskFile;
use App\Models\TaskPublish;
use App\Models\Papper;
use App\Utils\Code;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;

class TaskService extends BaseService
{
    /**
     * 创建数据
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function store(array $params) {
        if (!$this->checkParams($params)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            $failCount = 0;
            $successCount = 0;
            foreach($params['ids'] as $papperId) {
                if ($model = Task::where('papper_id', $papperId)
                    ->where('user_id', $params['user_id'])
                    ->where('type', $params['type'])
                    ->exists()) {
                    $failCount++;  
                    continue;
                }
                $model = new Task();
                $model->type = $params['type'];
                $model->user_id = $params['user_id'];
                $model->creator_id = $this::$userId;
                $model->papper_id = $papperId;
                $model->name = '';
                if (isset($params['number1']) && $params['number1']) {
                    $model->number1 = $params['number1'];
                }
                if (isset($params['number2']) && $params['number2']) {
                    $model->number2 = $params['number2'];
                }
                if ($model->number1 && $model->number2) {
                    $model->number3 = $model->number1 * $model->number2;
                }
                if (isset($params['pinggu_status']) && $params['pinggu_status']) {
                    $model->pinggu_status = $params['pinggu_status'];
                }
                if (isset($params['pinggu_date']) && $params['pinggu_date']) {
                    $model->pinggu_date = $params['pinggu_date'];
                }
                if (isset($params['agreement_at']) && $params['agreement_at']) {
                    $model->agreement_at = $params['agreement_at'];
                }
                if (isset($params['status']) && is_numeric($params['status'])) {
                    $model->status = $params['status'];
                }
                if (isset($params['sort']) && is_numeric($params['sort'])) {
                    $model->sort = $params['sort'];
                }
                if (isset($params['params']) && $params['params']) {
                    $model->params = $params['params'];
                }
                $successCount += $model->save() ? 1 : 0;
            }
            return [
                'successCount' => $successCount,
                'failCount' => $failCount
            ];
        });
    }

    /**
     * 数据信息
     * @param $id
     * @param bool $simple
     * @param bool $abnormal
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function show($id, $abnormal = true) {
        $model = Task::where('id', $id)->first();
        if (!$model && $abnormal){
            throw new \Exception('不存在的任务ID', Code::EMPTY_DATA);
        }
        return $model;
    }

    /**
     * 更新数据
     * @param $id
     * @param array $params
     * @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model|object|null
     * @throws \Exception
     */
    public function update($id, array $params) {
        if (!$this->checkParams($params, true)){
            throw new \Exception('请求参数验证不通过', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($id, $params){
            $model = $this->show($id);
            if (isset($params['params']) && $params['params']) {
                $model->params = $params['params'];
            }
            if (isset($params['user_id']) && is_numeric($params['user_id'])) {
                $model->user_id = $params['user_id'];
            }
            if (isset($params['sort']) && is_numeric($params['sort'])) {
                $model->sort = $params['sort'];
            }
            if (isset($params['status']) && is_numeric($params['status'])) {
                $model->status = $params['status'];
                if ($model->status === 3 || $model->status === 4) {
                    $model->sort = 50;
                }
            }
            if (isset($params['number1']) && $params['number1']) {
                $model->number1 = $params['number1'];
            }
            if (isset($params['number2']) && $params['number2']) {
                $model->number2 = $params['number2'];
            }
            if ($model->number1 && $model->number2) {
                $model->number3 = $model->number1 * $model->number2;
            }
            if (isset($params['agreement_at']) && $params['agreement_at']) {
                $model->agreement_at = $params['agreement_at'];
            }
            if (isset($params['pinggu_status']) && $params['pinggu_status']) {
                $model->pinggu_status = $params['pinggu_status'];
            }
            if (isset($params['pinggu_date']) && $params['pinggu_date']) {
                $model->pinggu_date = $params['pinggu_date'];
            }
            if (isset($params['videos'])) {
                if ($params['videos'] && is_array($params['videos'])) {
                    foreach ($params['videos'] as $video) {
                        $files[] = new TaskFile([
                            'type' => 2,
                            'papper_id' => $model->papper_id,
                            'task_id' => $model->id,
                            'path' => isset($video['name']) ? $video['name'] : $video
                        ]);
                    }
                    $model->files()->where('type', 2)->delete();
                    $model->files()->saveMany($files);
                    $files = [];
                } else {
                    $model->files()->where('type', 2)->delete();
                }
            }
            $model->save();
            return $this->show($id);
        });
    }

    /**
     * 删除数据
     * @param $id
     * @return mixed
     * @throws \Exception
     */
    public function destroy(array $ids = []) {
        if (!$this::$admin) {
            throw new \Exception('你没有权限进行删除', Code::LACK_OF_CONDITIONS);
        }
        return DB::transaction(function () use ($ids) {
            return Task::whereIn('id', $ids)->delete();
        });
    }

    /**
     * 数据分页
     * @param array $params
     * @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
     */
    public function lists(array $params = []) {
        $model = Task::with([
            'papper' => function ($query) {
                $query->with([
                    'folder' => function ($query) {
                        $query->with([
                            'packs',
                        ]);
                    },
                    'ip',
                    'title',
                    'tasks',
                    'user',
                    'need'
                ]);
            },
            'publish',
            'user',
            'video',
            'creator'
        ]);
        if (!$this::$admin || isset($params['is_self']) && $params['is_self'] == 1) {
            $model = $model->where('user_id', '=', $this::$userId);
        }
        if (isset($params['type']) && $params['type']) {
            $model = $model->where('type', '=', $params['type']);
        }
        if (isset($params['pinggu_status']) && $params['pinggu_status']) {
            $model = $model->where('pinggu_status', '=', $params['pinggu_status']);
        }
        if (isset($params['kpi_date']) && $params['kpi_date']) {
            $firstDay = date('Y-m-01', strtotime($params['kpi_date']));
            $lastDay = date('Y-m-t', strtotime($params['kpi_date']));
            $model = $model->where('pinggu_date', '>=', $firstDay);
            $model = $model->where('pinggu_date', '<=', $lastDay);
        }
        if (isset($params['pinggu_date']) && $params['pinggu_date']) {
            $params['pinggu_date'] = explode(',', $params['pinggu_date']);
            $model = $model->where('pinggu_date', '>=', $params['pinggu_date'][0]);
            $model = $model->where('pinggu_date', '<=', $params['pinggu_date'][1]);
        }
        if (isset($params['papper_id']) && $params['papper_id']) {
            $model = $model->where('papper_id', '=', $params['papper_id']);
        }
        if (isset($params['created_at']) && $params['created_at']) {
            $params['created_at'] = explode(',', $params['created_at']);
            $model = $model->where('created_at', '>=', $params['created_at'][0]);
            $model = $model->where('created_at', '<=', $params['created_at'][1]);
        }
        if (isset($params['agreement_at']) && $params['agreement_at']) {
            $params['agreement_at'] = explode(',', $params['agreement_at']);
            $model = $model->where('agreement_at', '>=', $params['agreement_at'][0]);
            $model = $model->where('agreement_at', '<=', $params['agreement_at'][1]);
        }
        if (isset($params['user_id']) && $params['user_id']) {
            $model = $model->where('user_id', '=', $params['user_id']);
        }
        if (isset($params['status']) && is_numeric($params['status'])) {
            $model = $model->where('status', '=', (int)$params['status']);
        }
        if (isset($params['papper_status']) && $params['papper_status']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('status', '=', (int)$params['papper_status']);
            });
        }
        if (isset($params['folder_id']) && $params['folder_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('folder_id', '=', $params['folder_id']);
            });
        }
        if (isset($params['ip_id']) && $params['ip_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('ip_id', '=', $params['ip_id']);
            });
        }
        if (isset($params['papper_user_id']) && $params['papper_user_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('user_id', '=', $params['papper_user_id']);
            });
        }
        
        if (isset($params['name']) && $params['name']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('name', 'like', '%'.$params['name'].'%');
            });
        }
        if (isset($params['publish_platform']) && $params['publish_platform']) {
            if (isset($params['publish_status']) && $params['publish_status'] == 2) {
                $model = $model->whereDoesntHave('publish', function ($query) use ($params){
                    $query->where('platform', $params['publish_platform']);
                });
            } else {
                $builder = TaskPublish::where('platform', $params['publish_platform']);
                if (isset($params['publish_status']) && is_numeric($params['publish_status'])) {
                    $builder->where('status', (int)$params['publish_status']);
                }
                if (isset($params['published_at']) && $params['published_at']) {
                    $params['published_at'] = explode(',', $params['published_at']);
                    $builder->where('published_at', '>=', $params['published_at'][0]);
                    $builder->where('published_at', '<=', $params['published_at'][1]);
                }
                $builder = $builder->pluck('task_id');
                $model = $model->whereIn('id', $builder);
            }
        }
        $lists = $model->orderBy('sort', 'asc')->orderBy('id', 'desc')->paginate(isset($params['per_page']) ? (int)$params['per_page'] : 15);
        return $lists;
    }

    function summary(array $params = []){
        $model = new Task();
        if (!$this::$admin || isset($params['is_self']) && $params['is_self'] == 1) {
            $model = $model->where('user_id', '=', $this::$userId);
        }
        if (isset($params['type']) && $params['type']) {
            $model = $model->where('type', '=', $params['type']);
        }
        if (isset($params['pinggu_status']) && $params['pinggu_status']) {
            $model = $model->where('pinggu_status', '=', $params['pinggu_status']);
        }
        if (isset($params['kpi_date']) && $params['kpi_date']) {
            $firstDay = date('Y-m-01', strtotime($params['kpi_date']));
            $lastDay = date('Y-m-t', strtotime($params['kpi_date']));
            $model = $model->where('pinggu_date', '>=', $firstDay);
            $model = $model->where('pinggu_date', '<=', $lastDay);
        }
        if (isset($params['papper_id']) && $params['papper_id']) {
            $model = $model->where('papper_id', '=', $params['papper_id']);
        }
        if (isset($params['user_id']) && $params['user_id']) {
            $model = $model->where('user_id', '=', $params['user_id']);
        }
        if (isset($params['folder_id']) && $params['folder_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('folder_id', '=', $params['folder_id']);
            });
        }
        if (isset($params['account_id']) && $params['account_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->where('account_id', '=', $params['account_id']);
            });
        }
        if (isset($params['ip_id']) && $params['ip_id']) {
            $model = $model->whereHas('papper', function ($query) use ($params){
                $query->whereHas('account', function ($query) use ($params){
                    $query->where('ip_id', '=', $params['ip_id']);
                });
            });
        }
        $result = $model->select(DB::raw('sum(number3) as kpi_point'))->get();
        $data['kpi_user_point'] = $result[0]->kpi_point;
        return $data;
    }

    /**
     * 验证参数
     * @param array $params
     * @param bool $isUpdate
     * @return array
     * @throws \Exception
     */
    private function checkParams(array $params, $isUpdate = false){
        $rules = [
            'type' => ['bail', 'required', 'integer'],
            'user_id' => ['bail', 'required', 'integer'],
            'ids' => ['bail', 'required', 'array']
        ];
        if ($isUpdate){
            // 删除必选条件
            foreach ($rules as $field => &$rule){
                if (isset($rule[1]) && $rule[1] == 'required') {
                    unset($rule[1]);
                }
            }
        }
        $validator = Validator::make($params, $rules, [], [
            'type' => '任务类型',
            'user_id' => '用户ID',
            'ids' => '文案ID组'
        ]);
        if ($validator->fails()) {
            throw new \Exception($validator->errors()->first(), Code::PARAMETER_ERROR);
        }
        return $params;
    }

    public function savePublish(array $params) {
        if (!isset($params['task_id']) || !$params['task_id']) {
            throw new \Exception('任务ID不能为空', Code::PARAMETER_ERROR);
        }
        if (!isset($params['platforms'])) {
            throw new \Exception('发布平台组不能为空', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            if (!$task = Task::where('id', $params['task_id'])->first()) {
                throw new \Exception('任务不存在', Code::PARAMETER_ERROR);
            }
            $task->publish()->delete();
            if ($params['platforms'] && is_array($params['platforms'])) {
                foreach ($params['platforms'] as $item) {
                    if (!$model = TaskPublish::where('task_id', $task->id)->where('platform', $item['platform'])->first()) {
                        $model = new TaskPublish();
                        $model->task_id = $task->id;
                        $model->platform = $item['platform'];
                    }
                    if (isset($item['created_at']) && $item['created_at']) {
                        $model->created_at = $item['created_at'];
                    }
                    if (isset($item['published_at']) && $item['published_at']) {
                        $model->published_at = $item['published_at'];
                    }
                    if (isset($item['status']) && is_numeric($item['status'])) {
                        $model->status = $item['status'];
                    }
                    if (isset($item['account_id']) && is_numeric($item['account_id'])) {
                        $model->account_id = $item['account_id'];
                    }
                    $model->save();
                }
            }
            $task->save();
            return $this->show($task->id);
        });
    }

    public function updateAll(array $params) {
        if (!isset($params['ids']) || !is_array($params['ids'])) {
            throw new \Exception('任务ID不能为空', Code::PARAMETER_ERROR);
        }
        if (!isset($params['mode']) || !$params['mode']) {
            throw new \Exception('修改模式不能为空', Code::PARAMETER_ERROR);
        }
        return DB::transaction(function () use ($params){
            if ($params['mode'] === 'taskStatusAll') {
                // 修改任务状态
                if (!isset($params['status']) || !is_numeric($params['status'])) {
                    throw new \Exception('状态错误', Code::PARAMETER_ERROR);
                }
                foreach($params['ids'] as $taskId) {
                    if (!$model = Task::where('id', $taskId)->first()) {
                        throw new \Exception('任务不存在'.$taskId, Code::PARAMETER_ERROR);
                    }
                    $model->status = $params['status'];
                    $model->save();
                }
                return true;
            } elseif ($params['mode'] === 'statusAll') {
                // 修改文案状态
                if (!isset($params['status']) || !is_numeric($params['status'])) {
                    throw new \Exception('状态错误', Code::PARAMETER_ERROR);
                }
                foreach($params['ids'] as $taskId) {
                    if (!$model = Task::where('id', $taskId)->first()) {
                        throw new \Exception('任务不存在'.$taskId, Code::PARAMETER_ERROR);
                    }
                    if (!$papper = Papper::where('id', $model->papper_id)->first()) {
                        throw new \Exception('文案不存在'.$taskId, Code::PARAMETER_ERROR);
                    }
                    $papper->status = $params['status'];
                    $papper->save();
                }
                return true;
            } elseif ($params['mode'] === 'kpiAll') {
                // 修改评估状态
                if (!isset($params['pinggu_status']) || !is_numeric($params['pinggu_status'])) {
                    throw new \Exception('评估状态错误', Code::PARAMETER_ERROR);
                }
                if (!isset($params['pinggu_date']) || !$params['pinggu_date']) {
                    throw new \Exception('评估日期不能为空', Code::PARAMETER_ERROR);
                }
                foreach($params['ids'] as $taskId) {
                    if (!$model = Task::where('id', $taskId)->first()) {
                        throw new \Exception('任务不存在', Code::PARAMETER_ERROR);
                    }
                    if (!$papper = Papper::where('id', $model->papper_id)->first()) {
                        throw new \Exception('文案不存在', Code::PARAMETER_ERROR);
                    }
                    if ($papper->number1 <= 0 || $papper->number2 <= 0 || $papper->number3 <= 0) {
                        throw new \Exception('文案未设置绩效分', Code::PARAMETER_ERROR);
                    }
                    $papper->pinggu_status = $params['pinggu_status'];
                    $papper->pinggu_date = $params['pinggu_date'];
                    $papper->save();
                    Task::where('papper_id', $model->papper_id)->update([
                        'pinggu_status' => $params['pinggu_status'],
                        'pinggu_date' => $params['pinggu_date']
                    ]);
                }
                return true;
            }
        });
    }
}
